FlutterのStackを使ってみた
大阪オフィスの山田です。道に落ちてるセミが急に動き出して必要以上にビビります。今回もFlutterです。Stack
を使ってみます。ちょっと描画時の規則でハマったのでそちらも合わせてご紹介します。
開発環境
Doctor summary (to see all details, run flutter doctor -v): [✓] Flutter (Channel beta, v0.5.1, on Mac OS X 10.13.5 17F77, locale ja-JP) [✓] Android toolchain - develop for Android devices (Android SDK 28.0.1) [✓] iOS toolchain - develop for iOS devices (Xcode 9.3) [✓] Android Studio (version 3.1) ✗ Flutter plugin not installed; this adds Flutter specific functionality. ✗ Dart plugin not installed; this adds Dart specific functionality. [!] VS Code (version 1.25.1) [✓] Connected devices (2 available)
VSCodeの警告が出ていますが、Extensionインストール済みです。
Flutterのバージョンは以下の通りです。
Flutter 0.5.1 • channel beta • https://github.com/flutter/flutter.git Framework • revision c7ea3ca377 (2 months ago) • 2018-05-29 21:07:33 +0200 Engine • revision 1ed25ca7b7 Tools • Dart 2.0.0-dev.58.0.flutter-f981f09760
前回、「この次はバージョンアップしよう」と書いてましたが、beta 6がまだ来てなかったので保留です。
今回やること
FlutterのWidget、Stack
の基本的な使い方のご紹介、それと私がハマったポイントについてご紹介します。
Stackの使い方
Stack
は以下の事ができます。
それでは使い方です。まずは基本です。
new Stack( children: <Widget>[ // ここに子の要素を配列で書いていく ], );
子の要素としてはpositioned
、non-positioned
なWidgetを設定することができます。positioned
はPositioned
Widgetでラップされたものを指します。それ以外はnon-positioned
となります。positioned
とnon-positioned
の関係性については後述します。子の要素は一番上が最背面、一番下が最前面になります。
Positioned Widgetを配置してみる
子の要素としてPositioned
Widgetを使って配置します。
Widget _buildStack() { return Stack( children: <Widget>[ Positioned( left: 20.0, top: 20.0, width: 100.0, height: 100.0, child: Container(color: Colors.indigo,), ), Positioned( left: 100.0, top: 100.0, right: 100.0, bottom: 200.0, child: Container(color: Colors.cyan,), ), ], ); }
Positioned
Widgetは、left
、top
、right
、bottom
、width
、height
を指定する事ができます。先ほどのサンプルプログラムの1つ目では幅と高さを決めて上から20、左から20を始点にして配置しています。2つ目は幅と高さを指定せず、上下左右の位置を指定しています。
non-positioned
なWidgetを配置してみる
Stack内の要素がPositioned
Widgetでラップされている場合、その要素はStack内でpositioned
とみなされます。それ以外はnon-positioned
です。この事を踏まえた上でソースコードと、結果の画像です。
Widget _buildStack() { return Stack( alignment: Alignment.bottomRight, children: <Widget>[ SizedBox( width: 200.0, height: 200.0, child: Container(color: Colors.orange,), ), SizedBox( width: 100.0, height: 100.0, child: Container(color: Colors.cyan,), ), Text("Test"), Positioned( top: 20.0, left: 20.0, right: 70.0, bottom: 70.0, child: Container(color:Colors.green), ) ] ); }
ここで結構ハマりました。上のソースでPositioned
が左上から20、右下から70指定されている(薄緑色の部分)ので、画面ほぼいっぱいに広がるのかと思っていました。1つ目の例だと画面いっぱいに広がって、その端から描画されていたのに...実はStack自体のサイズの決定には以下の規則があります。
なので1つ目の例ではnon-positionなWidgetが指定されていないため、Stackが可能な限り広がって、その端から計算されています。一方で2つ目の例ではnon-positionedなSizeBox(200x200)が最大領域となるので、それがStackのサイズになっています。
この例ではalignment
を指定していますが、これはnon-positionedなWidgetの配置位置を指定するものです。今回はbottomRightを指定していますが、これをtopLeftに指定するとTestの文字が左上に来ます。他にもfit
を指定する事で、non-positionedなWidgetの領域を可能な限り広めたり、最小限に留めたりする事ができます。
最後に
ちゃんとリファレンス読めば書いてあったりするのですが、動かしてみないとなんともイメージがつきにくい事ってありますよね。あと、動かすのって楽しいからついつい時間を忘れてしまう...